import * as PIXI from "pixi.js";
import Scene from "./components/Scene";
import Person from "./components/Person";
import Props from "./components/Props";

class App {
  app = null;

  MaterialPool = {};

  constructor(defaultInfo) {
    super();
    const { sceneInfo } = defaultInfo;
    this.app = new PIXI.Application({
      width: window.innerWidth,
      height: window.innerHeight - TAB_HEIGHT,
      backgroundColor: 0xb7d8ff,
      antialias: true, // default: false 反锯齿
      autoDensity: true, // canvas视图的CSS尺寸是否应自动调整为屏幕尺寸。
      resolution: 2, // default: 1 分辨率
    });
    this.scene = new Scene(this.app, sceneInfo);
  }

  static preloadResource(loader, tabContentList, onMaterialLoadProgress) {
    const { imgs, resources } = App.getAllResource(tabContentList);

    this.preloadTexture(loader, resources, onMaterialLoadProgress);
    this.preloadThumbnail(imgs);
  }

  static getAllResource(tabContentList) {
    const resources = [];
    const imgs = [];

    tabContentList.forEach((tabContent) => {
      tabContent.materialList.forEach((material) => {
        // 过滤已经加载过的
        if (!resources.find((resource) => resource.name === material.name)) {
          resources.push({ name: material.name, url: material.textureUrl });
        }
        if (
          material.thumbnail &&
          !imgs.find((img) => img === material.thumbnail)
        ) {
          imgs.push(material.thumbnail);
        }
      });
    });
    return {
      imgs,
      resources,
    };
  }

  // 预加载纹理
  static preloadTexture(loader, resources, onMaterialLoadProgress) {
    loader.add(resources);
    loader.onProgress.add(() => {
      onMaterialLoadProgress?.(Math.ceil(loader.progress));
    });
    loader.load();
  }

  // 预加载缩略图
  static preloadThumbnail(imgs) {
    return Promise.all(
      imgs.map((img) => {
        return new Promise((resolve, reject) => {
          const imgTemp = new Image();

          imgTemp.onload = () => resolve(undefined);
          imgTemp.onerror = () => reject();
          imgTemp.src = img;
        });
      })
    );
  }

  addPerson = (personInfo) => {
    const person = new Person(this.app, personInfo);
    this.MaterialPool[person.key] = person;
    person.on("Selected", this.onSelect);
    person.on("Delete", this.onDelete);
    return person;
  };

  addProps(propsInfo) {
    const prop = new Props(this.app, propsInfo);
    this.MaterialPool[prop.key] = prop;
    prop.on("Selected", this.onSelect);
    prop.on("Delete", this.onDelete);
    return prop;
  }

  onSelect = (selectItem) => {
    this.emit("ItemSelect", selectItem);

    if (!selectItem) {
      return;
    }

    for (const item of Object.entries(this.MaterialPool)) {
      const [, material] = item;

      if (material.key !== selectItem.key) {
        material.makeObjectUnEditable();
      } else {
        material.recoverEditable();
      }
    }
  };

  onDelete = (item) => {
    this.emit("ItemDelete", item);

    if (item && item.editableObject) {
      delete this.MaterialPool[item.key];

      this.app.stage.removeChild(item?.editableObject);
    }
  };

  mount(container) {
    container.appendChild(this.app.view);
  }
}
